import axios from 'axios'
import type {AxiosInstance, AxiosResponse, CreateAxiosDefaults} from "axios"
import NProgress from "nprogress";
import errorCode from "./errorCode";
import {message} from 'ant-design-vue';
const [messageApi, contextHolder] = message.useMessage();
import {getToken, removeToken} from './auth'
import {tansParams} from './ruoyi'
import {isExternal} from './validate'
import {throttle} from "@/utils/common";
import useStore from "@/store/index"
const request : AxiosInstance = axios.create(<CreateAxiosDefaults>{
    baseURL: "/api",  // 注意！！ 这里是全局统一加上了 '/api' 前缀，也就是说所有接口都会加上'/api'前缀在，页面里面写接口的时候就不要加 '/api'了，否则会出现2个'/api'，类似 '/api/api/user'这样的报错，切记！！！
    timeout: 100000
}
)

const t = throttle((msg) => {message.info(msg || "未登录，不可访问！", 10)},2000);

export const getUrl = function (url : string) {
    if (isExternal(url))
        return url;
    else
        return "/api" + url;
}
// 是否显示重新登录
export let isRelogin = {show: false};

// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token，对请求参数统一加密
request.interceptors.request.use(config => {
    // 是否需要设置 token
    // const isToken = (config.headers).isToken === false

    // NProgress.start()
    config.headers['Content-Type'] = 'application/json;charset=utf-8';
    //带token访问
    if (getToken()) {
        config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
    }

    // get请求映射params参数
    if (config.method === 'get' && config.params) {
        //把对象全部解构拼接到url
        let url = config.url + '?' + tansParams(config.params);
        url = url.slice(0, -1);
        config.params = {};
        config.url = url;
    }
    return config
}, error => {
    return Promise.reject(error)
});
// 可以在接口响应后统一处理结果
// 响应拦截器
request.interceptors.response.use(
    (res : AxiosResponse) => {
        // NProgress.done()
        // 二进制数据则直接返回
        if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
            // console.log("收到二进制数据")
            //res.data为blob对象。
            return res
        }
        // 未设置状态码则默认成功状态
        const code = res.data.code || 200;
        // 获取错误信息
        const msg = res.data.msg || errorCode[code] || errorCode['default']


        //统一异常处理 能处理即处理，之后把异常抛出
        switch (code) {
            case 401:   //认证失败，
                // removeToken()
                const {webConfig} =  useStore();
                if (!webConfig.isOpenLogin) {  //在页面访问后端接口认证失败，可能没token被拦截了，或者token，redis过期，或者伪造token解析出错。要先把token清除了。然后丢出去就行，全局路由守卫会跳到登录界面的
                    webConfig.isOpenLogin = true;
                } else { //在跳转路由时拿用户数据认证失败，可能没token被拦截了，或者token，redis过期，或者伪造token解析出错。统统跳到登录页进行登录
                    t(msg)
                }
                break;
            case 500:  //后端代码错/
                message.error(msg, 3);
                console.error(msg)
                break;
            case 200:  //成功返回
                return res.data;
            default:  //具体的业务错误，显示错误。抛出去给业务调用者处理即可
                message.error(msg, 3);

        }
        //上面已经显示错误信息了，页面接送到就不要再打印了
        //以上错误抛出去。返回值：一个被拒绝的 Promise对象。根据接口的需求进行捕获
        return Promise.reject(new Error(msg))
    },
    error => {
        console.log("错误响应：")
        console.error(error)
        let msg = error.message;
        if (msg == "Network Error") {
            msg = "后端接口连接异常";
        } else if (msg.includes("timeout")) {
            msg = "系统接口请求超时";
        } else if (msg.includes("Request failed with status code")) {
            msg = "系统接口" + msg.substr(msg.length - 3) + "异常";
        }

        message.error(msg, 3);
        return Promise.reject(error)
    }
)

export type AjaxResult<T = any> = {
    code:number,
    msg:string,
    data:T
}

export type page = {
    pageNum: number;
    pageSize: number;
    reasonable?:boolean;
    orderByColumn?:string;
    isAsc?: "ascending" | "descending"
}


// 传入后端返回的res即可
export const download = (res) => {
    // 获取文件的文件名
    const fileName = res.headers['content-disposition'].substring(
        res.headers['content-disposition'].indexOf('filename=') + 9,
        res.headers['content-disposition'].length
    )
    // 判断当前浏览器的a标签是否支持下载
    if ('download' in document.createElement('a')) {
        // 如果支持就创建a标签
        const downloadLink = document.createElement('a')
        // 为blob对象创建一个本地URL
        const url = window.URL.createObjectURL(res.data)
        // 将url赋值给其href属性
        downloadLink.href = url
        // 将文件名给到download属性
        downloadLink.setAttribute('download', fileName)
        // 将a标签添加到文档中
        document.body.appendChild(downloadLink)
        // 点击下载文件
        downloadLink.click()
        // 从文档中移除a标签
        document.body.removeChild(downloadLink)
    } else {
        // 如果浏览器不支持download属性,兼容ie
        window.navigator.msSaveBlob(res.data, fileName)
    }
}



export default request


